/*
 * Author: vdaras
 */


#include "../sdl/SDLException.h"
#include "../MouseEvent.h"
#include "ImageButton.h"
#include "Exception.h"

namespace gui
{


/**
 * Constructor initializes the Abstract Button parent class and then opens the desired
 * images for the display part of this Image Button. If any of the image's could not
 * be opened an exception is thrown.
 *
 * @param name: the identifier of this Component
 * @param regImage: path of the regular display of this button
 * @param highlightImage: path of the display of this button when it's highlighted
 * @param clickedImage: path of the display of this button when it's clicked
 */

ImageButton::ImageButton(const std::string& name, const std::string& regImage, const std::string& highlightImage, const std::string& clickedImage)
:
AbstractButton(name, 0, 0)
{
    //load images, if an error occurrs notify caller
    try
    {
        m_images[REGULAR].reset( new sdl::Image( regImage ) );
        m_images[HIGHLIGHTED].reset( new sdl::Image( highlightImage ) );
        m_images[CLICKED].reset( new sdl::Image( clickedImage ) );
    }
    catch( sdl::Exception &exc )
    {
        throw Exception( "Image Button could not be created! Probably one of the specified images doesn't exist on disk." );
    }


    int imageWidth = m_images[REGULAR]->GetWidth( );
    int imageHeight = m_images[REGULAR]->GetHeight( );

    m_visiblePart.w = imageWidth;
    m_visiblePart.h = imageHeight;

    //set the size of the Image Button based on it's regular image display
    SetWidth( imageWidth );
    SetHeight( imageHeight );
    
    UpdateVisiblePart( );
}


/**
 * Constructor initializes the Abstract Button parent class, adds the Image Button to
 * the specified container @x,y and then opens the desired images for the display part of this Image Button.
 * If any of the image's could not be opened an exception is thrown.
 *
 * @param name: the identifier of this Component
 * @param parent: this Component's container
 * @param x,y : position of the Component inside its' Container.
 * @param regImage: path of the regular display of this button
 * @param highlightImage: path of the display of this button when it's highlighted
 * @param clickedImage: path of the display of this button when it's clicked
 */

ImageButton::ImageButton(const std::string& name, Container* parent, int x, int y, const std::string& regImage, const std::string& highlightImage, const std::string& clickedImage)
:
AbstractButton(name, parent, x, y, 0, 0)
{
    try
    {
        m_images[REGULAR].reset( new sdl::Image( regImage ) );
        m_images[HIGHLIGHTED].reset( new sdl::Image( highlightImage ) );
        m_images[CLICKED].reset( new sdl::Image( clickedImage ) );
    }
    catch( sdl::Exception &exc )
    {
        throw Exception( "Image Button could not be created! Probably one of the specified images doesn't exist on disk." );
    }
     
    m_visiblePart.w = m_images[REGULAR]->GetWidth( );
    m_visiblePart.h = m_images[REGULAR]->GetHeight( );
 
    SetWidth( m_images[REGULAR]->GetWidth( ) );
    SetHeight( m_images[REGULAR]->GetHeight( ) );
    
    UpdateVisiblePart( );
}


ImageButton::~ImageButton()
{
}


/**
 * Resizes this ImageButton.
 *
 * @param width: new width.
 * @param height: new height.
 */

void ImageButton::Resize(int width, int height)
{
    
}


/**
 * Changes the regular display of the Image Button to the image located @
 * path.
 *
 * @param path: image on disk
 */

void ImageButton::SetRegularImage(const std::string& path)
{
    std::auto_ptr< sdl::Image > tempImage;

    try
    {
        //load image to a temporary Image Surface
        tempImage.reset( new sdl::Image( path ) );
    }
    catch( sdl::Exception &exc )
    {
        //if an error occurs return
        return;
    }

    //swap current regular image with the temporary one
    std::swap( m_images[REGULAR], tempImage );

    //if the current display is the regular image
    if( m_currentDisplay == REGULAR )
    {
        //set Image Button's size to the new one
        SetWidth( m_images[REGULAR]->GetWidth( ) );
        SetHeight( m_images[REGULAR]->GetHeight( ) );
    }
}


/**
 * Changes the highlighted display of the Image Button to the image located @
 * path.
 *
 * @param path: image on disk
 */

void ImageButton::SetHighlightImage(const std::string& path)
{
    std::auto_ptr< sdl::Image > tempImage;

    try
    {
        //load image to a temporary Image Surface
        tempImage.reset( new sdl::Image( path ) );
    }
    catch( sdl::Exception &exc )
    {
        //if an error occurs return
        return;
    }

    //swap current regular image with the temporary one
    std::swap( m_images[HIGHLIGHTED], tempImage );

    //if the current display is the regular image
    if( m_currentDisplay == HIGHLIGHTED )
    {
        //set Image Button's size to the new one
        SetWidth( m_images[HIGHLIGHTED]->GetWidth( ) );
        SetHeight( m_images[HIGHLIGHTED]->GetHeight( ) );
    }
}


/**
 * Changes the clicked display of the Image Button to the image located @
 * path.
 *
 * @param
 * path: image on disk
 */

void ImageButton::SetClickedImage(const std::string& path)
{
    std::auto_ptr< sdl::Image > tempImage;

    try
    {
        //load image to a temporary Image Surface
        tempImage.reset( new sdl::Image( path ) );
    }
    catch( sdl::Exception &exc )
    {
        //if an error occurs return
        return;
    }

    //swap current regular image with the temporary one
    std::swap( m_images[CLICKED], tempImage );

    //if the current display is the regular image
    if( m_currentDisplay == CLICKED )
    {
        //set Image Button's size to the new one
        SetWidth( m_images[CLICKED]->GetWidth( ) );
        SetHeight( m_images[CLICKED]->GetHeight( ) );
    }
}


/**
 * Draws the Image Button on a surface.
 *
 * @param target: the target surface.
 */

void ImageButton::Draw(sdl::Surface* target) const
{
    m_images[m_currentDisplay]->Blit( GetX( ), GetY( ), target, &m_visiblePart );
}


/**
 * Updates the Image Button.
 */

void ImageButton::Update()
{
}


};
